﻿using System;

namespace configstore.CSM.plugins
{
    using ExcelConfig;
    using ExcelConfig.Config;
    using SanlieHash.GuoMi;
    using SanlieHash;
    using SanlieHash.Fast;
    using configstore.CSM.Common;
    using configstore.CSM.Dto;
    /// <summary>
    /// 应用专属接口
    /// </summary>
    internal class AppPlug : ConfigStorePluginBase
    {
        protected override string ListenUri { get; } = "/store/config";
        internal SM4 sm4 = new SM4();
        protected override async Task OnRequest(ConfigStoreSession session)
        {
            if (session.IsPost(ListenUri))
            {
                var output = new ConfigStoreOutput();
                output.Success = true;

                if (output.Success)
                {
                    var data = await session.GetData<ConfigStoreInput>();
                    if (data == null) goto SEND_APP_REP;

                    var name = data.GetText("name");
                    var zone = data.GetText("zone");
                    var rootPath = AppConfig.Text("配置存放目录");
                    var cfgPath = Path.Combine(rootPath, zone);
                    var filePath = Path.Combine(cfgPath, $"{name}{ExcelConfigSetting.CONFIG_SUFFIX}");
                    switch (data.Method)
                    {
                        /**生成新的配置文件*/
                        case "new":
                            if (! Directory.Exists(cfgPath)) Directory.CreateDirectory(cfgPath);
                            if (File.Exists(Path.Combine(cfgPath, $"{name}{ExcelConfigSetting.CONFIG_SUFFIX}"))) goto SEND_APP_REP;
                            using (var emptycfg = AppConfig.EmptyStream())
                            using (var newfile = File.Create(filePath))
                            {
                                emptycfg.CopyTo(newfile);
                                newfile.Flush();
                            }
                            goto SEND_APP_REP;
                        case "ls":
                            var lspassword = data.GetText("password");
                            if (!Directory.Exists(cfgPath)) goto SEND_APP_REP;
                            string[] rlt;
                            if (!string.IsNullOrEmpty(zone)) rlt  =Directory.GetFiles(cfgPath, $"*{ExcelConfigSetting.CONFIG_SUFFIX}");
                            else rlt = Directory.GetDirectories(cfgPath);

                            if (rlt.Length == 0) goto SEND_APP_REP;
                            for(var i = 0; i < rlt.Length; i++)
                            {
                                if (rlt[i].ToLower().EndsWith(ExcelConfigSetting.CONFIG_SUFFIX)) rlt[i] = rlt[i].Substring(0, rlt[i].Length - ExcelConfigSetting.CONFIG_SUFFIX.Length);
                                rlt[i]= rlt[i].Replace('\\', '/');
                                var ix = rlt[i].LastIndexOf("/");
                                if (ix != -1) rlt[i] = rlt[i].Substring(ix + 1);
                            }
                            output.Params["value"] = FastGuoMi.EncryptSM4(string.Join(';', rlt), lspassword + session.Password);
                            goto SEND_APP_REP;
                        /**设置或读取 单个配置*/
                        case "value":
                            var vkey = data.GetText("key");
                            var vmethod = data.GetText("method");
                            var vcfg = new AppConfigFile(cfgPath, name);
                            var vpassword = data.GetText("password");
                            if (vmethod.Equals("set"))
                            {
                                var vvalue = data.GetText("value");
                                if (! string.IsNullOrEmpty(vvalue)) vvalue = FastGuoMi.DecryptSM4(vvalue, vpassword + session.Password);
                                vcfg.WriteText(vkey, vvalue);
                            }
                            else
                            {
                                var v = vcfg.Text(vkey);
                                if (string.IsNullOrEmpty(v)) goto SEND_APP_REP;
                                output.Params["value"] = FastGuoMi.EncryptSM4(v, vpassword + session.Password);
                            }
                            goto SEND_APP_REP;
                        /**放入配置文件*/
                        case "set":
                            var files = session.Files().ToArray();
                            if (files.Length == 1)
                            {
                                var file = files.First();

                                if (!Directory.Exists(cfgPath)) Directory.CreateDirectory(cfgPath);
                                if (File.Exists(filePath)) goto SEND_APP_REP;

                                sm4.New();
                                sm4.SetKey(FastHash.GetMD5Bytes(session.Password));
                                using (var mem = new MemoryStream(sm4.Decrypt(file.Data.ToArray())))
                                using (var newfile = File.Create(filePath))
                                {
                                    await mem.CopyToAsync(newfile);
                                    newfile.Flush();
                                }
                            }
                            goto SEND_APP_REP;
                        /**记录旧文件*/
                        case "setset":
                            var ffiles = session.Files().ToArray();
                            if (ffiles.Length == 1)
                            {
                                var file = ffiles.First();

                                if (!Directory.Exists(cfgPath)) Directory.CreateDirectory(cfgPath);
                                if (File.Exists(filePath)) File.Move(filePath, filePath +"."+ DateTime.UtcNow.Ticks.ToString() +".old");
                                
                                sm4.New();
                                sm4.SetKey(FastHash.GetMD5Bytes(session.Password));
                                using (var mem = new MemoryStream(sm4.Decrypt(file.Data.ToArray())))
                                using (var newfile = File.Create(filePath))
                                {
                                    await mem.CopyToAsync(newfile);
                                    newfile.Flush();
                                }
                            }
                            goto SEND_APP_REP;
                        /**获取配置文件*/
                        case "get":
                            await session.SendFile(200, $"{name}{ExcelConfigSetting.CONFIG_SUFFIX}", File.Open(Path.Combine(cfgPath, $"{name}{ExcelConfigSetting.CONFIG_SUFFIX}"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
                            return;
                    }

                }

            SEND_APP_REP:
                await session.Send(200, output);
                return;
            }

            await session.InvokeNext();
        }
    }
}
